package za.um.td.entity.level.gui;

import java.util.logging.Logger;

import za.um.td.entity.level.AbstractTerrain;

import com.jme.entity.Entity;
import com.jme.image.Texture;
import com.jme.image.Texture2D;
import com.jme.math.FastMath;
import com.jme.math.Vector2f;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.renderer.TextureRenderer;
import com.jme.scene.Node;
import com.jme.scene.Spatial.CullHint;
import com.jme.scene.shape.Box;
import com.jme.scene.shape.Quad;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;

public class MiniMap extends Entity {

	private static final Logger logger = Logger.getLogger(MiniMap.class
			.getName());

	private int miniMapWidth, miniMapHeight;
	private Vector2f pos;

	// camera members
	private TextureRenderer tRenderer;
	private Camera camera;
	private Texture2D fakeTex;
	private Node monitorNode;

	private AbstractTerrain terrain;

	public MiniMap(String id, Vector2f pos, int miniMapWidth,
			int miniMapHeight, AbstractTerrain terrain) {
		super(id);

		this.terrain = terrain;

		this.miniMapWidth = miniMapWidth;
		this.miniMapHeight = miniMapHeight;
		this.pos = pos;

		initSpatial();
	}

	private void initSpatial() {
		Node node = new Node();
		initSecurityCamera(node);
		initSecurityMonitor(node);
		setSpatial(node);

	}

	private void initSecurityCamera(Node node) {
		tRenderer = DisplaySystem.getDisplaySystem().createTextureRenderer(
				miniMapWidth - 2, miniMapHeight - 2,
				TextureRenderer.Target.Texture2D);

		Vector3f terrainCentre = terrain.getCentreLocation();

		camera = tRenderer.getCamera();

		float aspectRatio = (miniMapWidth - 2) / (miniMapHeight - 2);
		camera.setFrustumPerspective(45, aspectRatio, 1, 10000);

		// 0.392699 radians == 22.5 degrees which is half of the point of view == 45
		float xAdd = (terrain.getXLength() / 2.0f) / FastMath.tan(0.392699f);
		float zAdd = (terrain.getZLength() / 2.0f)
				/ FastMath.tan(0.392699f * aspectRatio);

		camera.setLocation(new Vector3f(terrainCentre.x, terrainCentre.y
				+ Math.max(xAdd, zAdd), terrainCentre.z));

		camera.lookAt(terrainCentre, new Vector3f(0, 0, 1));
		camera.update();
	}

	private void initSecurityMonitor(Node node) {
		monitorNode = new Node("Monitor Node");
		monitorNode.setRenderQueueMode(Renderer.QUEUE_ORTHO);
		Quad quad = new Quad("Monitor");
		quad.setZOrder(1);
		quad.updateGeometry(miniMapWidth - 2, miniMapHeight - 2);
		quad.setLocalTranslation(new Vector3f(pos.x, pos.y, 0));
		monitorNode.attachChild(quad);

		Quad quad2 = new Quad("Monitor");
		quad2.setZOrder(2);
		quad2.updateGeometry(miniMapWidth, miniMapHeight);
		quad2.getLocalTranslation().set(quad.getLocalTranslation());
		monitorNode.attachChild(quad2);

		// Ok, now lets create the Texture object that our scene will be
		// rendered to.
		tRenderer.setBackgroundColor(new ColorRGBA(0f, 0f, 0f, 1f));
		fakeTex = new Texture2D();
		fakeTex.setRenderToTextureType(Texture.RenderToTextureType.RGBA);
		tRenderer.setupTexture(fakeTex);
		TextureState screen = DisplaySystem.getDisplaySystem().getRenderer()
				.createTextureState();
		screen.setTexture(fakeTex);
		screen.setEnabled(true);
		quad.setRenderState(screen);
		monitorNode.updateGeometricState(0.0f, true);
		monitorNode.updateRenderState();

		node.attachChild(monitorNode);

		Box box = new Box("a box", Vector3f.ZERO, 1, 1, 1);

		tRenderer.render(terrain.getSpatial(), fakeTex);
	}

}
